# hostbuilder - Tools for DNS zonefile administration
# Copyright (c) 2010 Crown copyright
# 
# This file is part of hostbuilder.
# 
# hostbuilder is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# 
# hostbuilder is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with hostbuilder.  If not, see <http://www.gnu.org/licenses/>.

"""Install a DNS zone.

Extracts and incrementing the serial number from the existing zonefile"""

import sys
import os
import os.path
import tempfile

from time import localtime, strftime, time

from easyzone import easyzone
from easyzone.zone_reload import ZoneReload
from easyzone.zone_check import ZoneCheck


def get_serial(zonefile):
    """Retrieve the serial number from zonefile."""
    zone = easyzone.zone_from_file(zonefile)
    return zone.root.soa.serial


def generate_zonefile(template, serial):
    return open(template).read().replace('${SERIAL}', str(serial))


def increment_serial(serial):
    new_serial = int(strftime('%Y%m%d00', localtime(time())))
    if new_serial <= serial:
        new_serial = serial + 1
    return new_serial


def install(zone_name, template, outfile)
    serial = get_serial(outfile)

    current = open(outfile).read()
    generated = generate_zonefile(template, serial)

    if current == generated:
        # File has not changed
        sys.exit(0)

    new_serial = increment_serial(serial)

    output = generate_zonefile(template, newserial)

    f, tmpfname = tempfile.mkstemp(dir=os.path.dirname(outfile))

    try:
        f.write(output)
        f.close()
    except IOError:
        if os.path.exists(tempfname):
            os.unlink(tempfname)
        raise

    chk = ZoneCheck()
    if c.isValid(zone_name, tempfname):
        os.rename(tmpfname, outfile)

        r = ZoneReload()
        r.reload(zone_name)
    else:
        print >>sys.stderr, "Zone file error:", chk.error
        os.unlink(tempfname)


if __name__ == '__main__':
    zone_name, template, outfile = sys.argv[1:]

    install(zone_name, template, outfile)
